package com.xfcy.blog.config.websocket;

import org.elasticsearch.common.collect.CopyOnWriteHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author 晓风残月Lx
 * @date 2023/5/6 15:03
 */
@Component
@ServerEndpoint("/websocket")
public class WebSocketServer {

    private final Logger logger = LoggerFactory.getLogger(WebSocketServer.class);

    /**
     * 线程安全的无序集合
     */
    private static final CopyOnWriteArraySet<Session> SESSIONS = new CopyOnWriteArraySet<>();

    /**
     * 记录在线连接数
     */
    private static AtomicLong onlineNum = new AtomicLong();

    /**
     * 初始化连接
     *
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        try {
            SESSIONS.add(session);
            addOnlineNum();
            logger.info("有链接加入，当前人数为:{}", getOnlineNum());
            synchronized (session) {
                session.getBasicRemote().sendText(getOnlineNum());
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 连接关闭调用
     *
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        SESSIONS.remove(session);
        subOnlineNum();
        logger.info("有链接关闭，当前人数：{}", getOnlineNum());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     * @param session
     */
    @OnMessage
    public synchronized void sendMessage(String message, Session session) {
        logger.info("来自客户端的消息：{}", message);
        for (Session webSession : SESSIONS) {
            webSession.getAsyncRemote().sendText(getOnlineNum());
        }
    }

    private String getOnlineNum() {
        return String.valueOf(onlineNum.get());
    }

    /**
     * 在线连接数加1
     */
    private void addOnlineNum() {
        onlineNum.incrementAndGet();
    }

    /**
     * 在线连接数减1
     */
    private void subOnlineNum() {
        onlineNum.decrementAndGet();
    }


}
